package org.lisy.java.thread;

import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 * 阶段器
 * 
 * @author lisy
 */
public class PhaserOperate {

	private static Random random = new Random(System.currentTimeMillis());
	
	/**
	 * register(): 动态添加一个 parties
	 * bulkRegister(int parties): 动态添加多个 parties
	 * getRegisteredParties(): 获取当前的parties数
	 * arriveAndAwaitAdvance(): 到达并等待其他线程到达
	 * arriveAndDeregister(): 到达并注销该parties，这个方法不会使线程阻塞
	 * arrive(): 到达，但不会使线程阻塞
	 * awaitAdvance(int phase): 等待前行，可阻塞也可不阻塞，判断条件为传入的 phase 是否为当前 phaser 的 phase。如果相等则阻塞，反之不进行阻塞 
	 * awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit): 该方法与 awaitAdvance 类似，唯一不一样的就是它可以进行打断 
	 * getArrivedParties(): 获取当前到达的parties数
	 * getUnarrivedParties(): 获取当前未到达的parties数
	 * getPhase(): 获取当前属于第几阶段，默认从0开始，最大为integer的最大值
	 * isTerminated(): 判断当前phaser是否关闭
	 * forceTermination(): 强制关闭当前phaser
	 */
    public static void main(String[] args) {
        Phaser phaser = new Phaser(5){
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("================= step-" + phase + "-end =================== " + registeredParties);
                return super.onAdvance(phase, registeredParties);
            }
        };
		for (int i = 1; i <= 5; i++) {
			new Task(phaser, i).start();
		}
		// 监听第一个阶段结束 arrive() 和 awaitAdvance() 可以配合使用代替 CountDownLatch
		phaser.awaitAdvance(phaser.getPhase());
		System.out.println("No.main: first stage finished");
    }

    private static class Task extends Thread{
        private Phaser phaser;
        private String no;

        public Task(Phaser phaser, int no) {
            this.phaser = phaser;
            this.no = "No." + no;
        }

        @Override
        public void run() {
        	try {
        		// 跑步
                System.out.println(no + ": in " + phaser.getPhase() + " stage");
                System.out.println(no + ": start running");
                TimeUnit.SECONDS.sleep(random.nextInt(5));
                System.out.println(no + ": end running");
                // 多个 arriveAndAwaitAdvance 配合使用代替 CyclicBarrier
                phaser.arriveAndAwaitAdvance();
                /*synchronized (phaser) {
                	phaser.arrive();
                }*/

                // 骑行
                System.out.println(no + ": in " + phaser.getPhase() + " stage");
                System.out.println(no + ": start bicycle");
                TimeUnit.SECONDS.sleep(random.nextInt(5));
                System.out.println(no + ": end bicycle");
                phaser.arriveAndAwaitAdvance();
                
                // 跳远
                System.out.println(no + ": in " + phaser.getPhase() + " stage");
                System.out.println(no + ": start long jump");
                TimeUnit.SECONDS.sleep(random.nextInt(5));
                System.out.println(no + ": end long jump");
                phaser.arriveAndAwaitAdvance();
                System.out.println(no + ": end !");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
